import { ColDef } from 'ag-grid-community'
import { QueryParameterOptions, QueryUtils, Sort, SortWay, Utils } from 'monk-design/utils'
import { isEqual } from 'lodash-es'
import { AdBaseGridOptions } from './base.grid.options'
import { SelectAllParams } from './grid.interface'
import { BehaviorSubject } from 'rxjs'
import { InjectorModule } from 'monk-design/core'
import { ActivatedRoute, Router } from '@angular/router'

export class AdBaseGridContext<T = any> implements QueryParameterOptions {
  rowIdKeys: string[] = ['s_object_id', 'id']
  /**
   * 表格配置项
   */
  gridOptions: AdBaseGridOptions = new AdBaseGridOptions(this)
  /**
   * 是否跨页全选
   */
  isSelectAll: boolean = false
  /**
   * 跨页全选排除的档案id集合
   */
  selectAllExcludeIdList: string[] = []
  /**
   * 自增行id
   */
  private agGridRowId: number = 0
  /**
   * 数据id字典
   */
  private dataIdsMap = new Map<any[], string[]>()
  /**
   * 表格数据是否在渲染中
   */
  private gridInRendering: boolean = false

  private columnStateResetting: boolean = false
  rowData: T[] = []
  selectedRows: T[] = []
  columns: ColDef[] = []
  defaultSortField: string = ''
  defaultSortWay: SortWay = 'asc'
  sortList: Sort[] = []
  private routerContext = new RouterContext()
  constructor(public componentInstance: any, public gridSortCallback?: (params) => any) {
    this.defineProperty('rowData', [], this.setRowData)
    this.defineProperty('columns', [], this.setColumns)
  }

  /**
   * 拦截实例属性
   * @param key
   * @param val
   * @param setter
   */
  private defineProperty(key, val, setter: (v) => any) {
    Object.defineProperty(this, key, {
      get: () => val,
      set: (v) => {
        val = v
        setter && setter(v)
      },
    })
  }

  setDefaultSortInfo(sortField: string = '', sortWay: SortWay = 'asc') {
    this.defaultSortField = sortField
    this.defaultSortWay = sortWay
  }

  resetDefaultSortInfo() {
    this.setDefaultSortInfo()
  }

  /**
   * 渲染数据
   */
  private setRowData = () => {
    if (this.gridIsReady) {
      this.gridInRendering = true
      this.gridOptions.api.deselectAll()
      this.gridOptions.api.setRowData(this.rowData)
      this.gridOptions.api.hideOverlay()
      this.gridOptions.api.sizeColumnsToFit()
      this.selectAllChange?.(this.rowData)
      setTimeout(() => {
        this.gridInRendering = false
      })
    }
  }

  /**
   * 渲染配置列
   */
  private setColumns = () => {
    if (this.gridIsReady) {
      let column = this.columns.find((c) =>
        [this.componentInstance.parameter?.sortField].includes(c.colId || c.field)
      )
      if (!column) {
        column = this.columns.find((c) => [this.defaultSortField].includes(c.colId || c.field))
      }
      if (column) {
        if (
          Utils.getValueByKeys(column, ['colId', 'field']) ===
          this.componentInstance.parameter?.sortField
        ) {
          column.sort = this.componentInstance.parameter?.sortWay
        } else {
          column.sort = this.defaultSortWay
        }
      }
      this.columnStateResetting = true
      this.gridOptions.api.setColumnDefs(this.columns)
      this.gridOptions.api.sizeColumnsToFit()
      this.gridOptions.columnApi.resetColumnState()
      setTimeout(() => {
        this.columnStateResetting = false
      })
    }
  }

  onGridReady = () => {
    this.setColumns()
    this.setRowData()
  }

  getSelectAllParams(): SelectAllParams {
    if (!this.componentInstance.getQueryParams) {
      throw Error('请在组件中定义 getQueryParams 方法')
    }
    return {
      columns: QueryUtils.getFilterColumns(this.componentInstance.getQueryParams('select_all')),
      isSelectAll: this.isSelectAll,
      removeArchiveIds: this.selectAllExcludeIdList,
    }
  }

  /**
   * 取消所有选中项
   */
  deselectAll() {
    this.gridOptions?.api?.deselectAll()
  }

  /**
   * 取消跨页全选
   */
  cancelSelectAll() {
    this.isSelectAll = false
    this.selectAllExcludeIdList = []
    this.deselectAll()
  }

  /**
   * 跨页全选change事件
   * @param dataList
   */
  public selectAllChange(dataList?) {
    console.log(this.isSelectAll)

    if (!this.isSelectAll) {
      this.cancelSelectAll()
    } else {
      this.gridOptions.api.selectAll()
      dataList?.forEach((item) => {
        const matchId = this.selectAllExcludeIdList.find(
          (id) => Utils.getValueByKeys(item, this.rowIdKeys) === id
        )
        if (matchId) {
          this.gridOptions.api.getRowNode(matchId)?.setSelected(false)
        }
      })
    }
  }

  /**
   * 排序更改回调
   * @param e
   * @returns
   */
  onSortChanged(e) {
    if (this.columnStateResetting || !this.componentInstance.parameter) {
      return
    }
    const [sortInfo] = e.columnApi.getColumnState().filter((item) => item.sort)
    if (!this.shouldBreakNavigate?.(sortInfo)) {
      if (sortInfo) {
        sortInfo.colId = sortInfo.colId.replace('_1', '')
        this.componentInstance.parameter.sortWay = sortInfo.sort
        this.componentInstance.parameter.sortField = sortInfo.colId
      } else {
        this.componentInstance.parameter.sortField = ''
        this.componentInstance.parameter.sortWay = 'asc'
      }
    }
    const parameter = { ...this.componentInstance.parameter }
    Object.keys(parameter).forEach((key) => {
      parameter[key] = `${parameter[key]}`
    })
    if (this.gridSortCallback) {
      this.gridSortCallback.call(this.componentInstance, this.componentInstance.parameter)
    } else if (isEqual(parameter, this.routerContext.getQueryParams())) {
      this.componentInstance.getList()
    } else {
      this.routerContext.router.navigate([], {
        queryParams: { ...this.componentInstance.parameter },
      })
    }
  }

  /**
   * ag-grid 排序路由跳转断言
   * @param sortInfo
   * @returns
   */
  shouldBreakNavigate(sortInfo) {
    if (!this.componentInstance.parameter) {
      return
    }
    if (!sortInfo) {
      const { columns } = this.componentInstance.gridContext
      const defaultInColumns = Boolean(
        columns.find((item: ColDef) => (item.colId || item.field) === this.defaultSortField)
      )
      if (
        !this.componentInstance.parameter.sortField &&
        this.defaultSortField &&
        defaultInColumns
      ) {
        this.setSortInfo(this.defaultSortField, this.defaultSortWay)
      }
      const { sortField, sortWay } = this.componentInstance.parameter
      this.setSortInfo('', 'asc')
      if (
        sortField === this.defaultSortField &&
        sortWay === this.defaultSortWay &&
        this.defaultSortWay === 'desc' &&
        defaultInColumns
      ) {
        this.setSortInfo(this.defaultSortField, 'asc')
        this.columns = columns
        return true
      }
      if (this.defaultSortField && this.defaultSortWay && defaultInColumns) {
        this.setSortInfo(this.defaultSortField, this.defaultSortWay)
        this.columns = columns
        return true
      }
      if (!sortField) {
        return true
      }
    } else {
      const { sortField } = this.componentInstance.parameter
      if (
        !sortField &&
        sortInfo.colId === this.defaultSortField &&
        sortInfo.sort === this.defaultSortWay
      ) {
        this.setSortInfo(this.defaultSortField, this.defaultSortWay)
        return true
      }
    }
  }

  /**
   * 设置排序
   * @param sortField
   * @param sortWay
   */
  private setSortInfo(sortField: string, sortWay: SortWay) {
    this.componentInstance.parameter.sortField = sortField
    this.componentInstance.parameter.sortWay = sortWay
  }

  onRowSelected(e) {
    if (!this.isSelectAll || this.gridInRendering) {
      return
    }
    const itemId = Utils.getValueByKeys(e.data, this.rowIdKeys)
    const isSelected = e.node.selected
    const itemIndex = this.selectAllExcludeIdList.indexOf(itemId)
    if (isSelected && itemIndex !== -1) {
      this.selectAllExcludeIdList.splice(itemIndex, 1)
    } else if (!isSelected && itemIndex === -1) {
      this.selectAllExcludeIdList.push(itemId)
    }
  }

  onSelectionChanged() {
    this.selectedRows = this.gridOptions.api.getSelectedRows()
  }

  /**
   * 自定义行id
   * @param e
   * @returns
   */
  getRowNodeId = (e) => {
    const { dataIdsMap, rowData } = this
    if (!dataIdsMap.get(rowData)) {
      dataIdsMap.clear()
      dataIdsMap.set(rowData, [
        ...new Set<any>(rowData.map((item) => Utils.getValueByKeys(item, this.rowIdKeys))),
      ])
    }
    const id = Utils.getValueByKeys(e, this.rowIdKeys)
    const ids = dataIdsMap.get(rowData)
    if (id && rowData?.length === ids?.length && rowData?.length > 0) {
      return id
    } else {
      this.agGridRowId++
      return this.agGridRowId
    }
  }

  /**
   * 表格是否已经初始化
   */
  private get gridIsReady(): boolean {
    return Boolean(this.gridOptions.api)
  }

  /**
   * 数据是否为空
   */
  get isEmpty() {
    return this.rowData.length === 0
  }

  /**
   * 未选中表格行
   */
  get notSelected(): boolean {
    return this.selectedRows.length === 0
  }
}

class RouterContext {
  router: Router = InjectorModule.injector.get(Router)
  getQueryParams() {
    return (<BehaviorSubject<any>>(
      InjectorModule.injector.get(ActivatedRoute).queryParams
    )).getValue()
  }
}
